import { AnchorConfig, BaseNodeModel, EdgeConfig } from '@logicflow/core';
import { BaseInOutModel } from '../base/BaseInOutNode';

/**
 * 连接线管理
 */
class ConnectionManager {
  /**
   * 添加连线
   * @param sourceNode
   * @param targetNode
   * @param sourceAnchor
   * @param targetAnchor
   * @returns
   */
  addConnection = (
    sourceNode: BaseNodeModel,
    targetNode: BaseNodeModel,
    sourceAnchor: AnchorConfig,
    targetAnchor: AnchorConfig
  ) => {
    if (!window.behaviorDesigner) {
      return;
    }
    window.behaviorDesigner.addEdge({
      type: 'BaseBehaviorConnection',
      sourceNodeId: sourceNode.id,
      targetNodeId: targetNode.id,
      startPoint: { x: sourceAnchor.x, y: sourceAnchor.y },
      endPoint: { x: targetAnchor.x, y: targetAnchor.y },
    });
  };

  /**
   *
   * @param edge 删除连线
   * @returns
   */
  removeConnection = (edge: EdgeConfig) => {
    if (!window.behaviorDesigner || !edge) {
      return;
    }
    window.behaviorDesigner.deleteEdge(edge.id!);
  };

  /**
   * 连线添加事件处理函数
   */
  onConnectionAdd = ({ data }: { data: EdgeConfig }) => {
    if (!window.behaviorDesigner) {
      return;
    }
    const { behaviorDesigner } = window;
    const { id, sourceNodeId, targetNodeId } = data;
    const sourceNode = behaviorDesigner.getNodeModelById(sourceNodeId);
    const targetNode = behaviorDesigner.getNodeModelById(targetNodeId);

    // 判断出节点是否支持多条连线, 不支持的话需要删除其他连线, 仅出入节点支持多条连线
    if (!(sourceNode instanceof BaseInOutModel)) {
      this.removeConflictConnection(id!, sourceNode.id, 'source');
    }
    // 行为树仅支持单条入连线
    this.removeConflictConnection(id!, targetNode.id, 'target');
  };

  /**
   * 移除冲突的连线 \
   * 出节点和入节点仅支持单个连接
   * @param refConnectionId - 参照的连线 id
   * @param nodeId - 节点 id
   */
  removeConflictConnection = (
    refConnectionId: string,
    nodeId: string,
    nodeType: 'source' | 'target'
  ) => {
    const { behaviorDesigner } = window;
    const edges =
      nodeType === 'source'
        ? behaviorDesigner.getEdgeModels({
            sourceNodeId: nodeId,
          })
        : behaviorDesigner.getEdgeModels({
            targetNodeId: nodeId,
          });
    edges.forEach(({ id }) => {
      if (id === refConnectionId) {
        return;
      }
      behaviorDesigner.deleteEdge(id);
    });
  };
}

export default new ConnectionManager();
